// USystemUtils.cpp: implementation of the USystemUtils class.
//
//define _CRT_SECURE_NO_WARNINGS

#include "libutilsconfig.h"
#include "sstream"
#include "usystemutils.h"
#include "uStringUtils.h"
#include <string>

//#include "stringstream"
//#include "stringutils.h"
//#pragma comment(lib,"ws2_32.lib")
//#pragma comment(lib,"version.lib")


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


extern std::string GetProcessorSeial(bool withSeparator);

long getHardDriveComputerID (std::vector<HDDiskInfo>* infos);

using namespace std;
LIB_NS_BEGIN







tstring USystemUtils::GetModuleFilename(HINSTANCE hInstance )
{
    TCHAR thisName[MAX_PATH];
    ::GetModuleFileName(hInstance, thisName, sizeof(thisName));
    return thisName;
}


tstring USystemUtils::GetRootVolumeSerialNumber(const TCHAR* root )
{
    ULONG serial = 0;
    ::GetVolumeInformation (root,NULL,NULL,&serial,NULL,NULL,NULL,NULL);
#if defined(_UNICODE) || defined(UNICODE)
	wstringstream ss;
#else
    stringstream ss;
#endif
    ss<<serial;
    return ss.str();
}


ULONGLONG USystemUtils::GetCurrentUTCMilliseconds()
{
    FILETIME fileTime;
    ::GetSystemTimeAsFileTime(&fileTime);
    ULARGE_INTEGER u_lar;
    memcpy(&u_lar,&fileTime,sizeof(fileTime));
    ULONG64 rtn = u_lar.QuadPart;
    
    return rtn;
}








tstring USystemUtils::GetHostName()
{
	TCHAR HostName[MAX_PATH];
	DWORD buflen = MAX_PATH;
#ifdef WIN32		
	int sts = GetComputerName(HostName, &buflen);		
#else
	int sts = gethostname(HostName, buflen);		
#endif		
	
	if (!sts) 
		HostName[0] = _T('\0');
	return HostName;
}




void USystemUtils::ClearLastError()
{
	::SetLastError(0);
}
//
//bool USystemUtils::GetuniqueTempName( tstring& strTempName )
//{
//	//strTempName="";
//	////Get the temporary files directory.
//	//TCHAR szTempPath [MAX_PATH];
//	//DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);
//	//if (dwResult==0)
//	//	return false;
//	//
//	////Create a unique temporary file.
//	//TCHAR szTempFile[MAX_PATH];
//	//UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempFile);
//	//if (dwResult==0)
//	//	return false;
//	//
//	//strTempName=szTempFile;
//	//return true;
//	return false;
//}

bool USystemUtils::DeleteFiletoRecycle(LPCTSTR pszPath)
{
	SHFILEOPSTRUCT  shDelFile;
	memset(&shDelFile,0,sizeof(SHFILEOPSTRUCT));
	shDelFile.fFlags |= FOF_SILENT;      // don't report progress
	shDelFile.fFlags |= FOF_NOERRORUI;     // don't report errors
	shDelFile.fFlags |= FOF_NOCONFIRMATION;    // don't confirm delete
	// Copy pathname to double-NULL-terminated string.
	//
	TCHAR buf[_MAX_PATH + 1]; // allow one more character
	_tcscpy(buf, pszPath);   // copy caller's pathname
	buf[_tcslen(buf)+1]=0;   // need two NULLs at end 
	
	// Set SHFILEOPSTRUCT params for delete operation
	shDelFile.wFunc = FO_DELETE;       // REQUIRED: delete operation
	shDelFile.pFrom = buf;         // REQUIRED: which file(s)
	shDelFile.pTo = NULL;          // MUST be NULL
	shDelFile.fFlags |= FOF_ALLOWUNDO;    // ..send to Recycle Bin

	return SHFileOperation(&shDelFile) == 0 ? true : false;    // do it!
}


void USystemUtils::System( tstring cmd )
{
#if defined(UNICODE) || defined(_UNICODE)	
	::system(UStrConvUtils::WstringToString(cmd).c_str());
#else
	system(cmd.c_str());
#endif
}



bool USystemUtils::AddRunPath( const TCHAR* newpath,bool bfirst /*= true*/ )
{
	tstring curpath = USystemUtils::GetEnv(_T("Path"));
	if (bfirst)
	{
		curpath = tstring(newpath) + _T(";") + curpath;
	}
	else
	{
		curpath = curpath +_T(";") + newpath + _T(";");
	}
	return SetEnv(_T("Path"),curpath.c_str());
}

//bool USystemUtils::RemoveRunPath( const TCHAR* thepath )
//{
//	return false;
//	/*tstring curpath = GetEnv("Path");
//
//	LIB_NS::UStrUtils::Strings pathitems;
//	LIB_NS::UStrUtils::Strings newpathitems;
//	LIB_NS::UStrUtils::StrSplit(pathitems,curpath.c_str(),";");
//	for (LIB_NS::UStrUtils::Strings::iterator it = pathitems.begin(); it != pathitems.end(); it++)
//	{
//		if (*it != thepath && it->size() != 0)
//		{
//			newpathitems.push_back(*it);
//		}
//	}
//	tstring newpath = LIB_NS::UStrUtils::StrMerge(newpathitems,";");
//	return SetEnv("Path",newpath.c_str());*/
//
//}


bool USystemUtils::ShellOpenFile( tstring cmd,int nCmdShow /*= SW_SHOW*/ )
{
	HINSTANCE hInstance = ShellExecute(NULL, _T("open"), cmd.c_str(), NULL, NULL, nCmdShow);  
	if (hInstance <= (HINSTANCE) 32)
		return false;
	return true;
}

tstring USystemUtils::GetSimpleUUID()
{
#if defined (UNICODE) || defined(_UNICODE)
	wstringstream ss;
#else
	stringstream ss;
#endif
	
	TCHAR buffer[65];
	_ui64tot( USystemUtils::GetCurrentUTCMilliseconds (),buffer,10);
	ss << (USystemUtils::GetRootVolumeSerialNumber () ) << buffer;
	return ss.str ();
}

tstring USystemUtils::GetEnv( const tstring& key )
{
#ifdef WIN32

	TCHAR buffer[1024];
	memset(buffer,0,sizeof(buffer));
	int len = ::GetEnvironmentVariable(key.c_str(),buffer,sizeof(buffer));
	if (len == 0)
		return _T("");
	else
		return buffer;
#else
	return ::getenv(key);
#endif
}

bool USystemUtils::SetEnv( const TCHAR* key,const TCHAR* val )
{
#if defined WINDOWS || defined(_WINDOWS_)
	return ::SetEnvironmentVariable(key,val) == TRUE ? true : false;
#else
	tstring data = UStrConvUtils::Format( _T("%s=%s"),key,val);// tstring(key) + "=" + val;
	return ::_putenv(data.c_str()) == 0 ? true : false;
#endif
}

tstring USystemUtils::GetErrorMsg( DWORD dwError /*= GetLastError()*/ )
{
	tstring szError;
	HLOCAL hlocal = NULL;
	BOOL fOk = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
		NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (PTSTR) &hlocal, 0, NULL);

	if (!fOk)
	{
		// Is it a network-related error?
		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL,DONT_RESOLVE_DLL_REFERENCES);
		if (hDll != NULL)
		{
			FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM,
				hDll, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),(PTSTR) &hlocal, 0, NULL);

			FreeLibrary(hDll);
		}
	}

	if (hlocal != NULL)
	{
		szError = (LPCTSTR) LocalLock(hlocal);
		LocalFree(hlocal);
	}
	else
	{
		szError = _T("Unkown Error");
	}

	return szError;
}




std::string USystemUtils::GetCPUID( bool seperate /*= false*/ )
{
	std::string ret = GetProcessorSeial(seperate);
	return ret;
}

std::string USystemUtils::GetHDID( int index /*= 0*/ )
{
	std::vector<HDDiskInfo> infos;
	getHardDriveComputerID (&infos);
	if (infos.size()>0)
	{
		return infos[0].serial;

	}
	return "";
	
//	PrintIdeInfo(index,)
}

LIB_NS_END